package com.rao.gmall.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.rao.gmall.common.cache.BloomName;
import com.rao.gmall.common.config.ItemRedissonConfig;
import com.rao.gmall.common.constant.RedisConst;
import com.rao.gmall.common.result.Result;
import com.rao.gmall.feign.search.SkuEsFeignClient;
import com.rao.gmall.model.list.Goods;
import com.rao.gmall.model.list.SearchAttr;
import com.rao.gmall.model.product.*;
import com.rao.gmall.product.mapper.*;
import com.rao.gmall.product.service.SkuInfoService;
import org.checkerframework.checker.units.qual.A;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author nzmxfan
 * @create 2021-08-06-1:08
 */
@Service
public class SkuInfoServiceImpl extends ServiceImpl<SkuInfoMapper, SkuInfo> implements SkuInfoService {

    @Resource
    SkuInfoMapper skuInfoMapper;

    @Resource
    SkuAttrValueMapper skuAttrValueMapper;

    @Resource
    SkuSaleAttrValueMapper skuSaleAttrValueMapper;

    @Resource
    SkuImageMapper skuImageMapper;

    @Resource
    @Qualifier(BloomName.SKU)
    RBloomFilter<Object> skufilter;

    @Autowired
    SkuEsFeignClient skuEsFeignClient;

    @Autowired
    ThreadPoolExecutor executor;

    @Autowired
    BaseCategory3Mapper baseCategory3Mapper;

    @Autowired
    BaseCategory2Mapper baseCategory2Mapper;

    @Autowired
    BaseCategory1Mapper baseCategory1Mapper;

    @Autowired
    BaseTrademarkMapper baseTrademarkMapper;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveSkuInfo(SkuInfo skuInfo) {
        // 向 sku_info 添加基本信息
        skuInfoMapper.insert(skuInfo);
        Long id = skuInfo.getId();
        Long spuId = skuInfo.getSpuId();

        // 将 skuAttrValueList 添加到 sku_attr_value
        List<SkuAttrValue> skuAttrValueList = skuInfo.getSkuAttrValueList();
        for (SkuAttrValue skuAttrValue : skuAttrValueList) {
            skuAttrValue.setSkuId(id);
            skuAttrValueMapper.insert(skuAttrValue);
        }

        // 将 skuSaleAttrValueList 添加到 sku_sale_attr_value
        List<SkuSaleAttrValue> skuSaleAttrValueList = skuInfo.getSkuSaleAttrValueList();
        for (SkuSaleAttrValue skuSaleAttrValue : skuSaleAttrValueList) {
            skuSaleAttrValue.setSkuId(id);
            skuSaleAttrValue.setSpuId(spuId);
            skuSaleAttrValueMapper.insert(skuSaleAttrValue);
        }

        // 将 skuImageList 添加到 sku_image
        List<SkuImage> skuImageList = skuInfo.getSkuImageList();
        for (SkuImage skuImage : skuImageList) {
            // 写入 sku_id 属性
            skuImage.setSkuId(id);
            skuImageMapper.insert(skuImage);
        }
        //  第三步：新增 sku 信息后，向布隆过滤器中添加一个占位，供后续过滤请求使用
        String bloomKey = RedisConst.SKUKEY_PREFIX + id + RedisConst.SKUKEY_SUFFIX;
        skufilter.add(bloomKey);
    }

    /**
     * 根据 sku 获取数据，并通过异步编排方式封装为 Goods 对象
     * @param skuId
     */
    public void onSale(Long skuId){
        // 将数据库状态改为 1（0：下架；1：上架）
        skuInfoMapper.updateStatus(skuId, 1);

        // 将数据保存到 es 中
        Goods goods = new Goods();

        CompletableFuture<SkuInfo> skuInfoFuture = CompletableFuture.supplyAsync(()->{
            SkuInfo skuInfo = skuInfoMapper.selectById(skuId);
            // 1、封装基本信息
            goods.setId(skuInfo.getId());
            goods.setTitle(skuInfo.getSkuName());
            goods.setDefaultImg(skuInfo.getSkuDefaultImg());
            return skuInfo;
        },executor);

        // 2、封装价格
        CompletableFuture<Void> priceFuture = CompletableFuture.runAsync(() -> {
            BigDecimal skuPrice = skuInfoMapper.getSkuPrice(skuId);
            goods.setPrice(skuPrice);
        }, executor);

        // 3、封装品牌信息
        CompletableFuture<Void> baseTrademarkFuture = CompletableFuture.runAsync(() -> {
            //  goods.setCreateTime(new Date());  //不在这里准备时间，以es的处理为准
            BaseTrademark baseTrademark = baseTrademarkMapper.selectById(skuId);
            goods.setTmId(baseTrademark.getId());
            goods.setTmName(baseTrademark.getTmName());
            goods.setTmLogoUrl(baseTrademark.getLogoUrl());
        }, executor);

        // 4、封装分类
        CompletableFuture<Void> categoryFuture = skuInfoFuture.thenAcceptAsync((skuInfo) -> {
            // 封装 3 级分类
            BaseCategory3 baseCategory3 = baseCategory3Mapper.selectById(skuInfo.getCategory3Id());
            goods.setCategory3Id(baseCategory3.getId());
            goods.setCategory3Name(baseCategory3.getName());
            // 封装 2 级分类
            BaseCategory2 baseCategory2 = baseCategory2Mapper.selectById(baseCategory3.getCategory2Id());
            goods.setCategory2Id(baseCategory2.getId());
            goods.setCategory2Name(baseCategory2.getName());
            // 封装 1 级分类
            BaseCategory1 baseCategory1 = baseCategory1Mapper.selectById(baseCategory2.getCategory1Id());
            goods.setCategory1Id(baseCategory1.getId());
            goods.setCategory1Name(baseCategory1.getName());
        }, executor);

        CompletableFuture<Void> searchAttrsFuture = CompletableFuture.runAsync(() -> {
            // 5、当前 SKU 对应的所有平台属性以及值
            List<SearchAttr> searchAttrs = skuAttrValueMapper.getBaseAttrAndValuesBySkuId(skuId);
            goods.setAttrs(searchAttrs);
        }, executor);

        CompletableFuture
                .allOf(skuInfoFuture,priceFuture,baseTrademarkFuture,categoryFuture,searchAttrsFuture).whenCompleteAsync((res,exc)->{
                    skuEsFeignClient.onSale(goods);
        },executor);
    }

    public void cancelSale(Long skuId){
        // 将数据库状态改为 0（0：下架；1：上架）
        skuInfoMapper.updateStatus(skuId, 0);
        // 把商品信息从搜索引擎移除
        CompletableFuture.runAsync(()->{
            skuEsFeignClient.deleteById(skuId);
        }, executor);
    }

    @Override
    public List<Long> getAllId() {
        return skuInfoMapper.getAllIds();
    }

}
